module add
(
	input wire sys_clk,
	input wire sys_rst_n,
	
	input wire exe_en,
	input wire work_ok,
	input wire [4:0] op_code_receive,
	input wire [2:0] reserve_bit_receive,
	input wire [7:0] op_rand_receive,
	
	inout wire [15:0] ctrl_bus,
	inout wire [15:0] addr_bus,
	inout wire [15:0] data_bus,

	inout wire job_ok
);

localparam IDLE = 6'd0;
localparam UPDATE_IP = 6'd1;
localparam DA_TO_IN1 = 6'd2;
localparam RAM_TO_IN0 = 6'd3;
localparam ARI_LOG_TO_IN2 = 6'd4;
localparam IN2_TO_REG = 6'd5;
localparam INSTRUCT_DONE0 = 6'd6;
localparam INSTRUCT_DONE = 6'd7;

wire [4:0] op_code_this;
reg [2:0] reserve_bit_buf;
reg [7:0] op_rand_buf;

reg [5:0] state;
reg [9:0] cnt;
reg busy_flag;

reg [15:0] ctrl_bus_represent;
reg [15:0] addr_bus_represent;
reg [15:0] data_bus_represent;
reg job_ok_represent;

assign op_code_this = 5'b00010;
assign ctrl_bus = ctrl_bus_represent;
assign addr_bus = addr_bus_represent;
assign data_bus = data_bus_represent;
assign job_ok = job_ok_represent;

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
	begin
		reserve_bit_buf <= 3'h0;
		op_rand_buf <= 8'h0;
	end
	else if (exe_en == 1'b1 && op_code_this == op_code_receive)
	begin
		reserve_bit_buf <= reserve_bit_receive;
		op_rand_buf <= op_rand_receive;
	end
	else
	begin
		reserve_bit_buf <= reserve_bit_buf;
		op_rand_buf <= op_rand_buf;
	end

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
		busy_flag <= 1'b0;
	else if (exe_en == 1'b1 && op_code_this == op_code_receive)
		busy_flag <= 1'b1;
	else if (state == INSTRUCT_DONE)
		busy_flag <= 1'b0;
	else
		busy_flag <= busy_flag;

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
		job_ok_represent <= 1'bz;
	else if (state == INSTRUCT_DONE0)
		job_ok_represent <= 1'b0;
	else if (state == INSTRUCT_DONE)
		job_ok_represent <= 1'b1;
	else
		job_ok_represent <= 1'bz;

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
		state <= IDLE;
	else if (exe_en == 1'b1 && op_code_this == op_code_receive)
		state <= UPDATE_IP;
	else if (state == UPDATE_IP && work_ok == 1'b1)
		state <= DA_TO_IN1;
	else if (state == DA_TO_IN1 && work_ok == 1'b1)
		state <= RAM_TO_IN0;
	else if (state == RAM_TO_IN0 && work_ok == 1'b1)
		state <= ARI_LOG_TO_IN2;
	else if (state == ARI_LOG_TO_IN2 && work_ok == 1'b1)
		state <= IN2_TO_REG;
	else if (state == IN2_TO_REG && work_ok == 1'b1)
		state <= INSTRUCT_DONE0;
	else if (state == INSTRUCT_DONE0)
		state <= INSTRUCT_DONE;
	else if (state == INSTRUCT_DONE)
		state <= IDLE;
	else
		state <= state;

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
		cnt <= 10'd0;
	else if (exe_en == 1'b1 && op_code_this == op_code_receive)
		cnt <= 10'd0;
	else if (work_ok == 1'b1)
		cnt <= 10'd0;
	else if (busy_flag == 1'b0)
		cnt <= 10'd100;
	else if (busy_flag == 1'b1 && cnt < 10'd100)
		cnt <= cnt + 10'd1;
	else
		cnt <= cnt;

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
	begin
		ctrl_bus_represent <= 16'hz;
		addr_bus_represent <= 16'hz;
		data_bus_represent <= 16'hz;
	end
	else if (state == UPDATE_IP && cnt == 10'd1)
	begin
		ctrl_bus_represent <= 16'hffff;
		addr_bus_represent <= 16'hz;
		data_bus_represent <= 16'hz;
	end
	else if (state == UPDATE_IP && cnt == 10'd2)
	begin
		ctrl_bus_represent <= 16'd24;
		addr_bus_represent <= 16'hz;
		data_bus_represent <= 16'hz;
	end
	else if (state == DA_TO_IN1 && cnt == 10'd1)
	begin
		ctrl_bus_represent <= 16'hffff;
		addr_bus_represent <= 16'h0;
		data_bus_represent <= 16'hz;
	end
	else if (state == DA_TO_IN1 && cnt == 10'd2)
	begin
		ctrl_bus_represent <= 16'd5;
		addr_bus_represent <= 16'h0;
		data_bus_represent <= 16'hz;
	end
	else if (state == RAM_TO_IN0 && cnt == 10'd1)
	begin
		ctrl_bus_represent <= 16'hffff;
		addr_bus_represent <= 16'h0;
		data_bus_represent <= 16'hz;
	end
	else if (state == RAM_TO_IN0 && cnt == 10'd2)
	begin
		ctrl_bus_represent <= 16'd12;
		addr_bus_represent <= {8'h0, op_rand_buf};
		data_bus_represent <= 16'hz;
	end
	else if (state == ARI_LOG_TO_IN2 && cnt == 10'd1)
	begin
		ctrl_bus_represent <= 16'hffff;
		addr_bus_represent <= 16'h0;
		data_bus_represent <= 16'hz;
	end
	else if (state == ARI_LOG_TO_IN2 && cnt == 10'd2)
	begin
		ctrl_bus_represent <= 16'd22;
		addr_bus_represent <= 16'd0;
		data_bus_represent <= 16'hz;
	end
	else if (state == IN2_TO_REG && cnt == 10'd1)
	begin
		ctrl_bus_represent <= 16'hffff;
		addr_bus_represent <= 16'h0;
		data_bus_represent <= 16'hz;
	end
	else if (state == IN2_TO_REG && cnt == 10'd2)
	begin
		ctrl_bus_represent <= 16'd2;
		addr_bus_represent <= 16'd0;
		data_bus_represent <= 16'hz;
	end
	else
	begin
		ctrl_bus_represent <= 16'hz;
		addr_bus_represent <= 16'hz;
		data_bus_represent <= 16'hz;
	end

endmodule